const mongoose = require("mongoose");
const bcrypt = require("bcrypt");
const jwt = require('jsonwebtoken');
const {
  AuthenticationError,
  ForbiddenError
} = require('apollo-server-express');
require('dotenv').config();

const gravatar = require('../util/gravatar');

module.exports = {
  newNote: async (parent, args, { models, user }) => {
    if(!user) {
      throw new AuthenticationError('You must be signed in to create a note');
    }
    return await models.Note.create({
      content: args.content,
      // 引用作者在Mongo数据库中的ID
      // 要在数据库中交叉引用数据，对应的models中的author字段也要修改
      author: mongoose.Types.ObjectId(user.id)
    });

    /* let noteValues = {
      id: String(notes.length + 1),
      content: args.content,
      author: 'Adam Scott'
    };

    notes.push(noteValues);
    return noteValues; */
  },
  deleteNote: async (parent, { id }, { models, user }) => {
    // 如果上下文没有用户，抛出AuthenticationError
    if(!user) {
      throw new AuthenticationError('You must be signed in to delete a note');
    }

    // 查找笔记
    const note = await models.Note.findById(id);
    // 如果笔记的属主与当前用户不匹配，抛出ForbiddenError
    if(note && String(note.author) !== user.id) {
      throw new ForbiddenError("You don't have permissions to delelte the note");
    }

    try {
      // 通过所有检查后删除笔记
      await models.remove();
      // await models.Note.findOneAndRemove({ _id: id });
      return true;
    } catch (err) {
      // 如果检查过程中发现错误，返回false
      return false;
    }
  },
  updateNote: async (parent, { id, content }, { models, user }) => {
    // 如果上下文没有用户，抛出AuthenticationError
    if(!user) {
      throw new AuthenticationError('You must be signed in to delete a note');
    }

    // 查找笔记
    const note = await models.Note.findById(id);
    // 如果笔记的属主与当前用户不匹配，抛出ForbiddenError
    if(note && String(note.author) !== user.id) {
      throw new ForbiddenError("You don't have permissions to delelte the note");
    }

    // 更新数据库中的笔记，返回更新后的笔记
    try {
      return await models.Note.findOneAndUpdate(
        {
          _id: id
        },
        {
          $set: {
            content
          }
        },
        {
          new: true
        }
      );
    } catch (err) {
      throw new Error('Error updating note');
    }
  },
  toggleFavorite: async (parent, { id }, {models, user }) => {
    // 如果上下文没有用户，抛出AuthenticationError
    if(!user) {
      throw new AuthenticationError();
    }

    // 检查用户是不是已经收藏了该篇笔记
    let noteCheck = await models.Note.findById(id);
    const hasUser = noteCheck.favoriteBy.indexOf(user.id);

    // 如果当前用户在列表中
    // 把用户从列表中删除，并把'favoriteCount'的值减少一个
    if(hasUser >= 0) {
      return await models.Note.findByIdAndUpdate(
        id,
        {
          $pull: {
            favoriteBy: mongoose.Types.ObjectId(user.id)
          },
          $inc: {
            favoriteCount: -1
          }
        },
        {
          // 把new设为true，返回更新后的笔记
          new: true
        }
      );
    } else {
      // 如果当前用户不在列表中
      // 把用户添加到列表中，并把'favoriteCount'的值增加一个
      return await models.Note.findByIdAndUpdate(
        id,
        {
          $push: {
            favoriteBy: mongoose.Types.ObjectId(user.id)
          },
          $inc: {
            favoriteCount: 1
          }
        },
        {
          new: true
        }
      )
    }
  },
  // 注册接口

  /* 
  默认注册的用户信息
  mutation {
    signUp(username:"jingqi", email: "jingqi@qq.com",password: "123456")
  }
  {
    "data": {
      "signUp": "eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJpZCI6IjYzY2QwNzFiNWYzYThiMmZiMGQ5ZDIyMCIsImlhdCI6MTY3NDM4MTA4NH0.dGMImuvPmxvEOkjCNchjGLuk7dBL8PDfQwHuaWnmsKo"
    }
  }
  {
    "Authorization": "eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJpZCI6IjYzY2QwNzFiNWYzYThiMmZiMGQ5ZDIyMCIsImlhdCI6MTY3NDM4MTA4NH0.dGMImuvPmxvEOkjCNchjGLuk7dBL8PDfQwHuaWnmsKo"
  }
  */
  signUp: async(parent, { username, email, password }, { models }) => {
    // 数据处理
    // 规范电子邮件地址
    email = email.trim().toLowerCase();
    // 计算密码的哈希值
    const hashed = await bcrypt.hash(password, 10);
    // 生成 Gravatar URL
    const avatar = gravatar(email);

    // 调用接口
    try {
      const user = await models.User.create({
        username,
        email,
        avatar,
        password: hashed
      })

      // 创建并返回 JWT
      return jwt.sign({ id: user._id }, process.env.JWT_SECRET);
    } catch (err) {
      console.log(err);
      // 如果创建账户遇到问题，抛出错误
      throw new Error('Error creating account');
    }
  },
  // 登录接口
  signIn: async(parent, { username, email, password }, { models }) => {
    if(email) {
      email = email.trim().toLowerCase()
    }

    const user = await models.User.findOne({
      $or: [{ email }, { username }]
    });

    // 如未找到用户，抛出AuthenticationError
    if(!user) {
      throw new AuthenticationError("Error signing in")
    }

    // 如果密码不匹配，抛出AuthenticationError
    const valid = await bcrypt.compare(password, user.password);
    if(!valid) {
      throw new AuthenticationError("Error signing in")
    }

    return jwt.sign({ id: user._id }, process.env.JWT_SECRET);
  }
};